﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
//using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace RainmeterCustomized
{
    public partial class SetActionForm : Form
    {
        public SetActionForm()
        {
            InitializeComponent();
        }

        private String action;

        public String Action
        {
            get { return this.action; }
        }

        #region 构建和解析动作
        /// <summary>
        /// 构建动作
        /// </summary>
        /// <param name="ActionName">动作名</param>
        /// <param name="ActionPath">程序路径</param>
        /// <param name="ActionArgs">参数</param>
        /// <returns></returns>
        private String CreateAction(String ActionName, String ActionPath, String ActionArgs)
        {
            StringBuilder meterData = new StringBuilder();
            meterData.Append("!Execute [");
            meterData.Append(ActionName);
            meterData.Append(" \"" + ActionPath + "\"");
            meterData.Append(" \"" + ActionArgs + "\"");
            meterData.Append("]");
            return meterData.ToString();
        }

        /// <summary>
        /// 解析动作
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        private List<VariablesClass.ProgramObject> AnalyseAction(String action)
        {
            List<VariablesClass.ProgramObject> proObjs = new List<VariablesClass.ProgramObject>();
            Regex regex = new Regex(@"\[.+\]");
            MatchCollection matchCollection = regex.Matches(action);
            foreach (Match match in matchCollection)
            {
                String str = match.Value.Replace(@"[", "");
                str = str.Replace(@"]", "");
                MessageBox.Show(str);
                String[] tokens = str.Split('"');

                List<String> newTokens = new List<String>();
                foreach (String s in tokens)
                {
                    if (String.IsNullOrEmpty(s.Trim())) continue;
                    newTokens.Add(s);
                }
                String name = "";
                String path = "";
                String args = "";
                switch (newTokens.Count)
                {
                    case 1:
                        {
                            name = newTokens[0];
                            if (name.StartsWith("#") && name.EndsWith("#") && Program.progList.ContainsKey(name))
                                path = Program.progList[name].ProgPath;
                            else
                            {
                                name = "";
                                path = newTokens[0];
                            }
                            break;
                        }
                    case 2:
                        {
                            name = newTokens[0];
                            if (name.StartsWith("#") && name.EndsWith("#") && Program.progList.ContainsKey(name))
                            {
                                path = Program.progList[name].ProgPath;
                                args = newTokens[1];
                                Program.progList[name].ProgArgs = args;
                            }
                            break;
                        }
                    case 3:
                        {
                            name = newTokens[0];
                            path = newTokens[1];
                            args = newTokens[2];
                            break;
                        }
                }
                VariablesClass.ProgramObject po = new VariablesClass.ProgramObject(name, path, args);
                proObjs.Add(po);
            }
            return proObjs;
        }
        #endregion

        private void SetActionForm_Load(object sender, EventArgs e)
        {
            this.updateProgDefLV();
        }

        private void updateProgDefLV()
        {
            progDefLV.BeginUpdate();
            progDefLV.Clear();
            //设置列表框的表头
            progDefLV.Columns.Add(new ColHeader("程序名", 60, HorizontalAlignment.Left, true));
            progDefLV.Columns.Add(new ColHeader("程序路径", 120, HorizontalAlignment.Left, true));
            progDefLV.Columns.Add(new ColHeader("程序参数", 60, HorizontalAlignment.Left, true));
            foreach (KeyValuePair<String, VariablesClass.ProgramObject> kvPair in Program.progList)
            {
                String progName = kvPair.Key;
                VariablesClass.ProgramObject progObj = (VariablesClass.ProgramObject)kvPair.Value;
                ListViewItem lvItem = new ListViewItem(progName);
                lvItem.SubItems.Add(progObj.ProgPath);
                lvItem.SubItems.Add(progObj.ProgArgs);
                progDefLV.Items.Add(lvItem);
            }
            progDefLV.EndUpdate();
        }
        #region 排序类
        /// <summary>
        /// An instance of the SortWrapper class is created for
        /// each item and added to the ArrayList for sorting.
        /// </summary>
        public class SortWrapper
        {
            internal ListViewItem sortItem;
            internal int sortColumn;


            // A SortWrapper requires the item and the index of the clicked column.
            public SortWrapper(ListViewItem Item, int iColumn)
            {
                sortItem = Item;
                sortColumn = iColumn;
            }

            // Text property for getting the text of an item.
            public string Text
            {
                get
                {
                    return sortItem.SubItems[sortColumn].Text;
                }
            }

            // Implementation of the IComparer
            // interface for sorting ArrayList items.
            public class SortComparer : IComparer
            {
                bool ascending;

                // Constructor requires the sort order;
                // true if ascending, otherwise descending.
                public SortComparer(bool asc)
                {
                    this.ascending = asc;
                }

                // Implemnentation of the IComparer:Compare
                // method for comparing two objects.
                public int Compare(object x, object y)
                {
                    SortWrapper xItem = (SortWrapper)x;
                    SortWrapper yItem = (SortWrapper)y;

                    string xText = xItem.sortItem.SubItems[xItem.sortColumn].Text.ToString();
                    string yText = yItem.sortItem.SubItems[yItem.sortColumn].Text.ToString();
                    return xText.CompareTo(yText) * (this.ascending ? 1 : -1);
                }
            }
        }
        #endregion

        /// <summary>
        ///   The ColHeader class is a ColumnHeader object with an 
        ///   added property for determining an ascending or descending sort.
        ///   True specifies an ascending order, false specifies a descending order.
        /// </summary>
        public class ColHeader : ColumnHeader
        {
            public bool ascending;
            public ColHeader(string text, int width, HorizontalAlignment align, bool asc)
            {
                this.Text = text;
                this.Width = width;
                this.TextAlign = align;
                this.ascending = asc;
            }
        }

        #region 按列排序
        /// <summary>
        /// 列表点击列排序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void progDefLV_ColClick(object sender, ColumnClickEventArgs e)
        {
            // Create an instance of the ColHeader class.
            ColHeader clickedCol = (ColHeader)progDefLV.Columns[e.Column];

            // Set the ascending property to sort in the opposite order.
            clickedCol.ascending = !clickedCol.ascending;

            // Get the number of items in the list.
            int numItems = progDefLV.Items.Count;

            //*/
            // Turn off display while data is repoplulated.
            progDefLV.BeginUpdate();

            // Populate an ArrayList with a SortWrapper of each list item.
            ArrayList SortArray = new ArrayList();
            for (int i = 0; i < numItems; i++)
            {
                SortArray.Add(new SortWrapper(progDefLV.Items[i], e.Column));
            }
            // 排序
            SortArray.Sort(0, SortArray.Count, new SortWrapper.SortComparer(clickedCol.ascending));

            // Clear the list, and repopulate with the sorted items.
            progDefLV.Items.Clear();

            for (int i = 0; i < numItems; i++)
                progDefLV.Items.Add(((SortWrapper)SortArray[i]).sortItem);

            progDefLV.EndUpdate();

        }
        #endregion

        private void cancelBt_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void okBt_Click(object sender, EventArgs e)
        {
            if (this.selfDefCheckBox.Checked)
            {
                this.action = this.selfDefActionTextBox.Text;
            }
            else
            {
                this.action = this.CreateAction(this.progNameTb.Text, this.progPathTb.Text, this.progArgsTb.Text);
            }
            Close();
        }

        private void selectBt_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                this.progPathTb.Text = ofd.FileName;
            }
        }

        private void progDefLV_Click(object sender, EventArgs e)
        {
            ListViewItem lvItem = progDefLV.SelectedItems[0];
            this.progNameTb.Text = lvItem.SubItems[0].Text;
            this.progPathTb.Text = lvItem.SubItems[1].Text;
            this.progArgsTb.Text = lvItem.SubItems[2].Text;
        }

        private void selfDefCB_CheckChanged(object sender, EventArgs e)
        {
            this.progNameTb.Enabled = !this.progNameTb.Enabled;
            this.progPathTb.Enabled = !this.progPathTb.Enabled;
            this.progArgsTb.Enabled = !this.progArgsTb.Enabled;
            this.selfDefActionTextBox.Enabled = !this.selfDefActionTextBox.Enabled;
        }


    }
}
